home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK2.toast / Development Kits (Disc 2) / OpenDoc / OpenDoc Development / Debugging Support / OpenDoc™ Source Code / Storage / LinkMgr.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-28  |  48.4 KB  |  1,763 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        LinkMgr.cpp
  3.  
  4.     Contains:    Implementation for ODLinkManager class.
  5.  
  6.     Owned by:    Craig Carper
  7.  
  8.     Copyright:    © 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.          <4>     5/24/96    jpa        1246074: SOM_CATCH --> SOM_TRY..SOM_ENDTRY
  13.          <3>     3/26/96    CC        1288720: Removed kODULongSequence value
  14.                                     type.
  15.          <2>     3/15/96    CC        1328345: Extracted code from
  16.                                     GetLinkAEHandler to make GetLink;
  17.                                     Extracted code from RequestLinkAEHandler to
  18.                                     make UseLinkEdition.
  19.  
  20.     To Do:
  21.     In Progress:
  22.         
  23. */
  24.  
  25. #define VARIABLE_MACROS
  26.  
  27. #define ODLinkManager_Class_Source
  28. #include <LinkMgr.xih>
  29.  
  30. #ifndef _EXCEPT_
  31. #include <Except.h>
  32. #endif
  33.  
  34. #ifndef _ODMEMORY_
  35. #include <ODMemory.h>
  36. #endif
  37.  
  38. #ifndef _ISOSTR_
  39. #include <ISOStr.h>
  40. #endif
  41.  
  42. #ifndef _PASCLSTR_
  43. #include <PasclStr.h>
  44. #endif
  45.  
  46. #ifndef SOM_Module_OpenDoc_StdProps_defined
  47. #include <StdProps.xh>
  48. #endif
  49.  
  50. #ifndef SOM_Module_OpenDoc_StdTypes_defined
  51. #include <StdTypes.xh>
  52. #endif
  53.  
  54. #ifndef SOM_Module_OpenDoc_StdDefs_defined
  55. #include <StdDefs.xh>
  56. #endif
  57.  
  58. #ifndef SOM_ODPart_xh
  59. #include <Part.xh>
  60. #endif
  61.  
  62. #ifndef SOM_ODSession_xh
  63. #include <ODSessn.xh>
  64. #endif
  65.  
  66. #ifndef SOM_ODContainer_xh
  67. #include <ODCtr.xh>
  68. #endif
  69.  
  70. #ifndef SOM_ODDocument_xh
  71. #include <Document.xh>
  72. #endif
  73.  
  74. #ifndef SOM_ODDraft_xh
  75. #include <Draft.xh>
  76. #endif
  77.  
  78. #ifndef SOM_ODStorageUnit_xh
  79. #include <StorageU.xh>
  80. #endif
  81.  
  82. #ifndef SOM_ODLink_xh
  83. #include <Link.xh>
  84. #endif
  85.  
  86. #ifndef SOM_ODLinkSource_xh
  87. #include <LinkSrc.xh>
  88. #endif
  89.  
  90. #ifndef SOM_ODLinkSpec_xh
  91. #include <LinkSpec.xh>
  92. #endif
  93.  
  94. #ifndef SOM_ODLinkIterator_xh
  95. #include <LinkItr.xh>
  96. #endif
  97.  
  98. #ifndef SOM_ODLinkSourceIterator_xh
  99. #include <LkSrcItr.xh>
  100. #endif
  101.  
  102. #ifndef _LINKDEFS_
  103. #include <LinkDefs.h>
  104. #endif
  105.  
  106. #ifndef _LINKDLGS_
  107. #include <LinkDlgs.h>
  108. #endif
  109.  
  110. #ifndef _ORDCOLL_
  111. #include <OrdColl.h>
  112. #endif
  113.  
  114. #ifndef _PLFMFILE_
  115. #include <PlfmFile.h>
  116. #endif
  117.  
  118. #ifndef SOM_Module_OpenDoc_Errors_defined
  119. #include <ErrorDef.xh>
  120. #endif
  121.  
  122. #ifndef __ERRORS__
  123. #include <Errors.h>
  124. #endif
  125.  
  126. #ifndef _BARRAY_
  127. #include <BArray.h>
  128. #endif
  129.  
  130. #ifndef _REFCTCOL_
  131. #include "RefCtCol.h"
  132. #endif
  133.  
  134. #ifndef _TEMPOBJ_
  135. #include <TempObj.h>
  136. #endif
  137.  
  138. #ifndef _STORUTIL_
  139. #include <StorUtil.h>
  140. #endif
  141.  
  142. #ifndef _USERSRCM_
  143. #include <UseRsrcM.h>
  144. #endif
  145.  
  146. // For smSystemScript
  147. #ifndef __SCRIPT__
  148. #include <Script.h>
  149. #endif
  150.  
  151. #ifndef __TEXTUTILS__
  152. #include <TextUtils.h>
  153. #endif
  154.  
  155. #ifndef _DLOGUTIL_
  156. #include <DlogUtil.h>
  157. #endif
  158.  
  159. #ifndef _STDTYPIO_
  160. #include <StdTypIO.h>
  161. #endif
  162.  
  163. #ifndef __GESTALT__
  164. #include <Gestalt.h>
  165. #endif
  166.  
  167. #ifndef __TOOLUTILS__
  168. #include <ToolUtils.h>
  169. #endif
  170.  
  171. #ifndef __NOTIFICATION__
  172. #include <Notification.h>
  173. #endif
  174.  
  175. #pragma segment ODLinkManager
  176.  
  177. //==============================================================================
  178. // Constants
  179. //==============================================================================
  180.  
  181. const Boolean kNotSysHandler = false;
  182.  
  183. // Apple event constants
  184. #define kODGetLinkEventID        'gtln'
  185. #define kODRequestLinkEventID    'rqln'
  186. #define keyEditionAlias            'edas'
  187. #define kODLinkSourceKey        'lksr'
  188.  
  189. const    ODUShort    kODStorageUnitRefLen    = 4;
  190. const    ODUShort    kODULongSize            = 4;
  191.  
  192. //==============================================================================
  193. // Local Function Prototypes
  194. //==============================================================================
  195. ODStatic StringPtr BuildErrorString(ODSShort strResourceID, ODError error);
  196.  
  197. ODStatic EditionContainerSpec NewEditionFile(Environment* ev,
  198.             PlatformFile* documentFile,
  199.             ODDraft* draft);
  200.     
  201. ODStatic void EditionFileName(Str255 fileName, ODUShort numb);
  202. ODStatic void TruncateFileName(Str255 fileName, Str63 numberString);
  203.     
  204. ODStatic ODULong NewEditionID(Environment *ev, ODDraft* draft);
  205.     
  206. ODStatic void RegisterPublishingLinks(Environment *ev, ODDraft* draft);
  207. ODStatic void RegisterSubscribingLinks(Environment *ev, ODDraft* draft);
  208. ODStatic void UpdateEditionFiles(Environment *ev, ODRefCntCollection* collection);
  209. ODStatic void DeleteEditionFiles(Environment *ev, ODRefCntCollection* collection);
  210. // ODStatic void RemoveAllLinksInCollection(Environment *ev, OrderedCollection* collection);
  211. ODStatic OSErr GetSectionFromEvent(const AppleEvent* theAppleEvent,
  212.                 SectionHandle* section);
  213. ODStatic void AppendULongToDraftProperty(Environment *ev,
  214.     ODDraft* draft, ODPropertyName prop, ODULong value);
  215. ODStatic ODBoolean SectionIDReserved(Environment *ev,
  216.     ODDraft* draft, ODULong requestedID);
  217. ODStatic ODULong PeekNextGlobalID(Environment *ev,
  218.     ODDraft* draft,
  219.     ODPropertyName globalProp);
  220. ODStatic ODULong ReserveGlobalID(Environment *ev,
  221.     ODDraft* draft,
  222.     ODPropertyName globalProp);
  223.  
  224. ODStatic OSErr ODPascal GetLinkAEHandler(
  225.                             const AppleEvent* theAppleEvent,
  226.                             AppleEvent* reply,
  227.                             long refCon);
  228. ODStatic OSErr ODPascal RequestLinkAEHandler(
  229.                             const AppleEvent* theAppleEvent,
  230.                             AppleEvent* reply,
  231.                             long refCon);
  232. ODStatic OSErr ODPascal SectionReadAEHandler(
  233.                             const AppleEvent* theAppleEvent,
  234.                             const AppleEvent* reply,
  235.                             long refCon);
  236. ODStatic OSErr ODPascal SectionWriteAEHandler(
  237.                             const AppleEvent* theAppleEvent,
  238.                             const AppleEvent* reply,
  239.                             long refCon);
  240. ODStatic OSErr ODPascal SectionScrollAEHandler(
  241.                             const AppleEvent* theAppleEvent,
  242.                             const AppleEvent* reply,
  243.                             long refCon);
  244.  
  245.  
  246. //==============================================================================
  247. // struct DraftInfo
  248. //==============================================================================
  249.  
  250. struct DraftInfo
  251. {
  252.     ODDraft*              draft;
  253.     ODRefCntCollection*    linksToExport;
  254.     ODRefCntCollection*    linksToDelete;
  255.     ODRefCntCollection*    newExportedLinks;
  256.     ODBoolean            linksImported;
  257. };
  258.  
  259. // ODObjectCollection is replaced by ODObjectOrdColl in RefCtCol.h in Utilities
  260.  
  261. //==============================================================================
  262. // class ODObjectCollection
  263. //==============================================================================
  264. // 
  265. // class ODObjectCollection : public OrderedCollection
  266. // {
  267. //     public:
  268. //         ODObjectCollection() : OrderedCollection()    {}
  269. //         ODVMethod ~ODObjectCollection()                {}
  270. // 
  271. //         ODMethod ODBoolean ElementsMatch(ElementType v1,ElementType v2) const;
  272. // };
  273.  
  274. //------------------------------------------------------------------------------
  275. // ODObjectCollection::ElementsMatch (OVERRIDE)
  276. //------------------------------------------------------------------------------
  277.  
  278. // ODBoolean ODObjectCollection::ElementsMatch(ElementType v1,ElementType v2) const
  279. // {
  280. //     Environment* ev = somGetGlobalEnvironment();
  281. //     return ODObjectsAreEqual(ev, (ODObject*) v1, (ODObject*) v2);
  282. // }
  283.  
  284. //==============================================================================
  285. // Static functions
  286. //==============================================================================
  287.  
  288. //------------------------------------------------------------------------------
  289. // LinkMgrNMResponse
  290. //------------------------------------------------------------------------------
  291.  
  292. ODStatic void ODPascal LinkMgrNMResponse(NMRecPtr theNMRecPtr)
  293. {
  294.     OSErr error = NMRemove(theNMRecPtr);
  295. }
  296.  
  297. //==============================================================================
  298. // class ODLinkManager
  299. //==============================================================================
  300.  
  301. //------------------------------------------------------------------------------
  302. // ODLinkManager::InitLinkManager
  303. //------------------------------------------------------------------------------
  304.  
  305. SOM_Scope void  SOMLINK ODLinkManagerInitLinkManager(ODLinkManager *somSelf, Environment *ev,
  306.         ODSession* session)
  307. {
  308.     ODLinkManagerData *somThis = ODLinkManagerGetData(somSelf);
  309.     ODLinkManagerMethodDebug("ODLinkManager","InitLinkManager");
  310.  
  311.     SOM_TRY
  312.  
  313.     /* Moved from somInit. SOM itself sets fields to zero
  314.     _fSuspendedUpdateLinks = (ODRefCntCollection*) kODNULL;
  315.     _fDraftInfos = (OrderedCollection*) kODNULL;
  316.     _fNMResponseUPP = (NMUPP) kODNULL;
  317.     _fNMRecPtr = (NMRecPtr) kODNULL;
  318.     */
  319.     somSelf->InitObject(ev);
  320.     
  321.     long  gestaltResult;
  322.     OSErr result;
  323.  
  324.     // Check if the Edition manager is present
  325.     result = Gestalt(gestaltEditionMgrAttr, &gestaltResult);
  326.     THROW_IF_ERROR (result, "Error from Gestalt");
  327.  
  328.     // The mysterious 31 is the bit position as BitTst uses a convention opposite to MC68000
  329.     if ( BitTst(&gestaltResult, (31 - gestaltEditionMgrPresent)) == false )
  330.         THROW(kODErrNoEditionManager);
  331.  
  332.     InitLinkDialogs(session);
  333.  
  334.     _fSuspendedUpdateLinks = new ODRefCntCollection(ev);
  335.     _fDraftInfos = new OrderedCollection;
  336.     _fNMResponseUPP = NewNMProc(LinkMgrNMResponse);
  337.     _fNMRecPtr = (NMRecPtr) ODNewPtr(sizeof(NMRec));
  338.     THROW_IF_NULL(_fNMRecPtr);
  339.     _fNMRecPtr->nmStr = kODNULL;    
  340.  
  341.     AEEventHandlerUPP theHandlerUPP ;
  342.     theHandlerUPP = NewAEEventHandlerProc( GetLinkAEHandler ) ;
  343.     THROW_IF_ERROR(AEInstallEventHandler(kODShellSignature,
  344.             kODGetLinkEventID, theHandlerUPP, (long)somSelf, kNotSysHandler));
  345.  
  346.     theHandlerUPP = NewAEEventHandlerProc( RequestLinkAEHandler ) ;
  347.     THROW_IF_ERROR(AEInstallEventHandler(kODShellSignature,
  348.             kODRequestLinkEventID, theHandlerUPP, (long)somSelf, kNotSysHandler));
  349.  
  350.     theHandlerUPP = NewAEEventHandlerProc( SectionReadAEHandler ) ;
  351.     THROW_IF_ERROR(AEInstallEventHandler(sectionEventMsgClass, sectionReadMsgID,
  352.             theHandlerUPP, (long)somSelf, kNotSysHandler));
  353.  
  354.     theHandlerUPP = NewAEEventHandlerProc( SectionWriteAEHandler );
  355.     THROW_IF_ERROR(AEInstallEventHandler(sectionEventMsgClass, sectionWriteMsgID,
  356.             theHandlerUPP, (long)somSelf, kNotSysHandler));
  357.  
  358.     theHandlerUPP = NewAEEventHandlerProc( SectionScrollAEHandler );
  359.     THROW_IF_ERROR(AEInstallEventHandler(sectionEventMsgClass, sectionScrollMsgID,
  360.             theHandlerUPP, (long)somSelf, kNotSysHandler));
  361.  
  362.     SOM_CATCH_ALL
  363.     SOM_ENDTRY
  364. }
  365.  
  366. //------------------------------------------------------------------------------
  367. // ODLinkManager::NewSectionID
  368. //------------------------------------------------------------------------------
  369.  
  370. SOM_Scope ODULong  SOMLINK ODLinkManagerNewSectionID(ODLinkManager *somSelf, Environment *ev,
  371.         ODDraft* draft)
  372. {
  373.     ODLinkManagerData *somThis = ODLinkManagerGetData(somSelf);
  374.     ODLinkManagerMethodDebug("ODLinkManager","NewSectionID");
  375.  
  376.     ODULong sectionID;
  377.  
  378.     SOM_TRY
  379.  
  380.     do 
  381.         sectionID = ReserveGlobalID(ev, draft, kODPropSectionID);
  382.     while
  383.         ( SectionIDReserved(ev, draft, sectionID) );
  384.         
  385.     return sectionID;
  386.  
  387.     SOM_CATCH_ALL
  388.     SOM_ENDTRY
  389.     return 0;
  390. }
  391.  
  392. //------------------------------------------------------------------------------
  393. // ODLinkManager::ReserveSectionID
  394. //------------------------------------------------------------------------------
  395.  
  396. SOM_Scope ODBoolean  SOMLINK ODLinkManagerReserveSectionID(ODLinkManager *somSelf, Environment *ev,
  397.         ODULong sectionID,
  398.         ODDraft* draft)
  399. {
  400.     ODLinkManagerData *somThis = ODLinkManagerGetData(somSelf);
  401.     ODLinkManagerMethodDebug("ODLinkManager","ReserveSectionID");
  402.  
  403.     SOM_TRY
  404.  
  405.     ODBoolean result = kODFalse;
  406.     
  407.     if ( sectionID >= PeekNextGlobalID(ev, draft, kODPropSectionID) )
  408.         if ( !SectionIDReserved(ev, draft, sectionID) )
  409.         {
  410.             AppendULongToDraftProperty(ev, draft, kODPropReservedSectionIDs, sectionID);
  411.             result = kODTrue;
  412.         }
  413.  
  414.     return result;
  415.  
  416.     SOM_CATCH_ALL
  417.     SOM_ENDTRY
  418.     return kODFalse;
  419. }
  420.  
  421. //-------------------------------------------------------------------------------------
  422. // ODLinkManager: ShowLinkUpdateAlert
  423. //-------------------------------------------------------------------------------------
  424.  
  425. SOM_Scope ODLinkUpdateResult  SOMLINK ODLinkManagerShowLinkUpdateAlert(ODLinkManager *somSelf, Environment *ev,
  426.         ODBaseLinkSource* link)
  427. {
  428.     ODLinkManagerData *somThis = ODLinkManagerGetData(somSelf);
  429.     ODLinkManagerMethodDebug("ODLinkManager","ShowLinkUpdateAlert");
  430.     
  431.     ODLinkUpdateResult result = kODLinkUpdateContinue; ODVolatile(result);
  432.  
  433.     SOM_TRY
  434.     
  435.         // When we leave the background, iterate over all the link sources
  436.         // that attempted to call ShowLinkUpdateAlert() in the background,
  437.         // showing the alert now and calling the links back with the
  438.         // resulting information.
  439.         
  440.         if ( _fInBackground )
  441.         {
  442.             result = kODLinkUpdateStop;
  443.             if ( !_fSuspendedUpdateLinks->Contains(link) )
  444.                 _fSuspendedUpdateLinks->AddLastAndAcquire(link);
  445.             result = kODLinkUpdateSuspend;
  446.         }
  447.         else
  448.         {
  449.             result = ( ::ShowLinkUpdateAlert() )? 
  450.                 kODLinkUpdateContinue : kODLinkUpdateStop;
  451.         }
  452.  
  453.     SOM_CATCH_ALL
  454.     
  455.     SOM_ENDTRY
  456.     
  457.     return result;
  458. }
  459.  
  460. //-------------------------------------------------------------------------------------
  461. // ODLinkManager: SuspendResume
  462. //-------------------------------------------------------------------------------------
  463.  
  464. #if ODDebug
  465. extern int gODButtonKeyNoEnterOkay;
  466. #endif
  467.  
  468. SOM_Scope void  SOMLINK ODLinkManagerSuspendResume(ODLinkManager *somSelf, Environment *ev,
  469.         ODEventData* event)
  470. {
  471.     ODLinkManagerData *somThis = ODLinkManagerGetData(somSelf);
  472.     ODLinkManagerMethodDebug("ODLinkManager","SuspendResume");
  473.  
  474.     const short kResumeMask = 0x01;    // High byte suspend/resume event 
  475.  
  476.     ODBoolean inBackground = (event->message & kResumeMask) == 0;
  477.     _fInBackground = inBackground;
  478.  
  479.     SOM_TRY
  480.     
  481.         // When we leave the background, show the alert and iterate over all the
  482.         // link sources that attempted to call ShowLinkUpdateAlert() in the 
  483.         // background, calling the links back with the resulting alert information.
  484.         
  485.         if ( !inBackground )
  486.         {
  487.             ODBaseLinkSource* link = (ODBaseLinkSource*) _fSuspendedUpdateLinks->RemoveFirst();
  488.             if (link)
  489.             {
  490.  
  491.                 ODLinkUpdateResult result = ( ::ShowLinkUpdateAlert() )? 
  492.                     kODLinkUpdateContinue : kODLinkUpdateStop;
  493.  
  494.                 while ( link )
  495.                 {
  496.                     TempODRefCntObject tempLink = link; // ensure it is released
  497.                     
  498.                     // Ignore errors returned by LinkUpdateAlertCompleted
  499.                     TRY
  500.                         link->LinkUpdateAlertCompleted(ev, result);
  501.                     CATCH_ALL
  502.                     ENDTRY
  503.                     
  504.                     link = (ODBaseLinkSource*) _fSuspendedUpdateLinks->RemoveFirst();
  505.                 }
  506.             }
  507.         }
  508.  
  509.     SOM_CATCH_ALL
  510.     
  511.     SOM_ENDTRY
  512. }
  513.  
  514. //------------------------------------------------------------------------------
  515. // ODLinkManager::UnsavedExportedLinks
  516. //------------------------------------------------------------------------------
  517.  
  518. SOM_Scope ODBoolean  SOMLINK ODLinkManagerUnsavedExportedLinks(ODLinkManager *somSelf, Environment *ev,
  519.         ODDraft* draft)
  520. {
  521.     ODLinkManagerData *somThis = ODLinkManagerGetData(somSelf);
  522.     ODLinkManagerMethodDebug("ODLinkManager","UnsavedExportedLinks");
  523.  
  524.     SOM_TRY
  525.  
  526.     DraftInfo* info = somSelf->GetDraftInfo(ev, draft);
  527.  
  528.     if ( info != (DraftInfo*) kODNULL ) 
  529.     {
  530.         return info->newExportedLinks->Count() > 0;
  531.     }
  532.     else
  533.         return kODFalse;
  534.  
  535.     SOM_CATCH_ALL
  536.     SOM_ENDTRY
  537.     return kODFalse;
  538. }
  539.  
  540. //------------------------------------------------------------------------------
  541. // ODLinkManager::AnyLinkImported
  542. //------------------------------------------------------------------------------
  543.  
  544. SOM_Scope ODBoolean  SOMLINK ODLinkManagerAnyLinkImported(ODLinkManager *somSelf, Environment *ev,
  545.         ODDraft* draft)
  546. {
  547.     ODLinkManagerData *somThis = ODLinkManagerGetData(somSelf);
  548.     ODLinkManagerMethodDebug("ODLinkManager","AnyLinkImported");
  549.  
  550.     SOM_TRY
  551.  
  552.     DraftInfo* info = somSelf->GetDraftInfo(ev, draft);
  553.  
  554.     if ( info != (DraftInfo*) kODNULL ) 
  555.     {
  556.         return info->linksImported;
  557.     }
  558.     else
  559.         return kODFalse;
  560.  
  561.     SOM_CATCH_ALL
  562.     SOM_ENDTRY
  563.     return kODFalse;
  564. }
  565.  
  566. //------------------------------------------------------------------------------
  567. // ODLinkManager::DraftOpened
  568. //------------------------------------------------------------------------------
  569.  
  570. SOM_Scope void  SOMLINK ODLinkManagerDraftOpened(ODLinkManager *somSelf, Environment *ev,
  571.         ODDraft* draft)
  572. {
  573.     ODLinkManagerData *somThis = ODLinkManagerGetData(somSelf);
  574.     ODLinkManagerMethodDebug("ODLinkManager","DraftOpened");
  575.  
  576.     SOM_TRY
  577.  
  578.     DraftInfo* info = somSelf->GetDraftInfo(ev, draft);
  579.     
  580.     if ( info == (DraftInfo*) kODNULL ) 
  581.     {
  582.         somSelf->NewDraftInfo(ev, draft);
  583.         RegisterSubscribingLinks(ev, draft);
  584.         RegisterPublishingLinks(ev, draft);
  585.     }
  586.  
  587.     SOM_CATCH_ALL
  588.     SOM_ENDTRY
  589. }
  590.  
  591. //------------------------------------------------------------------------------
  592. // ODLinkManager::DraftSaved
  593. //------------------------------------------------------------------------------
  594.  
  595. SOM_Scope void  SOMLINK ODLinkManagerDraftSaved(ODLinkManager *somSelf, Environment *ev,
  596.         ODDraft* draft)
  597. {
  598.     ODLinkManagerData *somThis = ODLinkManagerGetData(somSelf);
  599.     ODLinkManagerMethodDebug("ODLinkManager","DraftSaved");
  600.  
  601.     SOM_TRY
  602.  
  603.     DraftInfo* info = somSelf->GetDraftInfo(ev, draft);
  604.     
  605.     if ( info != (DraftInfo*) kODNULL ) 
  606.     {
  607.         UpdateEditionFiles(ev, info->linksToExport);
  608.         // old: RemoveAllLinksInCollection(ev, info->linksToExport);
  609.         info->linksToExport->RemoveAndReleaseAll();
  610.  
  611.         DeleteEditionFiles(ev, info->linksToDelete);
  612.         // old: RemoveAllLinksInCollection(ev, info->linksToDelete);
  613.         info->linksToDelete->RemoveAndReleaseAll();
  614.  
  615.         // old: RemoveAllLinksInCollection(ev, info->newExportedLinks);
  616.         info->newExportedLinks->RemoveAndReleaseAll();
  617.         
  618.         info->linksImported = kODFalse;
  619.     }
  620.     else 
  621.     {
  622.         WARN("Draft is not opened yet.");
  623.     }
  624.  
  625.     SOM_CATCH_ALL
  626.     SOM_ENDTRY
  627. }
  628.  
  629. //------------------------------------------------------------------------------
  630. // ODLinkManager::DraftClosing
  631. //------------------------------------------------------------------------------
  632.  
  633. SOM_Scope void  SOMLINK ODLinkManagerDraftClosing(ODLinkManager *somSelf, Environment *ev,
  634.         ODDraft* draft)
  635. {
  636.     ODLinkManagerData *somThis = ODLinkManagerGetData(somSelf);
  637.     ODLinkManagerMethodDebug("ODLinkManager","DraftClosing");
  638.  
  639.     SOM_TRY
  640.  
  641.     DraftInfo* info = somSelf->GetDraftInfo(ev, draft);
  642.  
  643.     if ( info != (DraftInfo*) kODNULL ) 
  644.     {
  645.         // old: RemoveAllLinksInCollection(ev, info->linksToExport);
  646.         // new: info->linksToExport->RemoveAndReleaseAll();
  647.         ODDeleteObject(info->linksToExport); // calls RemoveAndReleaseAll()
  648.  
  649.         // old: RemoveAllLinksInCollection(ev, info->linksToDelete);
  650.         // new: info->linksToDelete->RemoveAndReleaseAll();
  651.         ODDeleteObject(info->linksToDelete); // calls RemoveAndReleaseAll()
  652.  
  653.         DeleteEditionFiles(ev, info->newExportedLinks);
  654.         // old: RemoveAllLinksInCollection(ev, info->newExportedLinks);
  655.         // new: info->newExportedLinks->RemoveAndReleaseAll();
  656.         ODDeleteObject(info->newExportedLinks); // calls RemoveAndReleaseAll()
  657.  
  658.         _fDraftInfos->Remove(info);
  659.         delete info;
  660.     }
  661.  
  662.     SOM_CATCH_ALL
  663.     SOM_ENDTRY
  664. }
  665.  
  666. //------------------------------------------------------------------------------
  667. // ODLinkManager::ExportOnSave
  668. //------------------------------------------------------------------------------
  669.  
  670. SOM_Scope ODBoolean  SOMLINK ODLinkManagerExportOnSave(ODLinkManager *somSelf, Environment *ev,
  671.         ODLink* link,
  672.         ODBoolean doExport)
  673. {
  674.     ODLinkManagerData *somThis = ODLinkManagerGetData(somSelf);
  675.     ODLinkManagerMethodDebug("ODLinkManager","ExportOnSave");
  676.  
  677.     ODBoolean wereToExport = kODFalse;
  678.  
  679.     SOM_TRY
  680.  
  681.     DraftInfo* info = somSelf->GetDraftInfo(ev, link->GetStorageUnit(ev)->GetDraft(ev));
  682.     if ( info != (DraftInfo*) kODNULL ) 
  683.     {
  684.         wereToExport = info->linksToExport->Contains(link);
  685.         if ( wereToExport && !doExport ) 
  686.         {
  687.             info->linksToExport->RemoveAndRelease(link);
  688.             // link->Release(ev);
  689.         }
  690.         else if ( !wereToExport && doExport ) 
  691.         {
  692.             info->linksToExport->AddLastAndAcquire(link);
  693.             // link->Acquire(ev);
  694.         }
  695.     }
  696.  
  697.     return wereToExport;
  698.  
  699.     SOM_CATCH_ALL
  700.     SOM_ENDTRY
  701.     return kODFalse;
  702. }
  703.  
  704. //------------------------------------------------------------------------------
  705. // ODLinkManager::DeleteOnSave
  706. //------------------------------------------------------------------------------
  707.  
  708. SOM_Scope ODBoolean  SOMLINK ODLinkManagerDeleteOnSave(ODLinkManager *somSelf, Environment *ev,
  709.         ODLink* link,
  710.         ODBoolean doDelete)
  711. {
  712.     ODLinkManagerData *somThis = ODLinkManagerGetData(somSelf);
  713.     ODLinkManagerMethodDebug("ODLinkManager","DeleteOnSave");
  714.  
  715.     ODBoolean wereToDelete = kODFalse;
  716.  
  717.     SOM_TRY
  718.  
  719.     DraftInfo* info = somSelf->GetDraftInfo(ev, link->GetStorageUnit(ev)->GetDraft(ev));
  720.     if ( info != (DraftInfo*) kODNULL ) 
  721.     {
  722.         wereToDelete = info->linksToDelete->Contains(link);
  723.         if ( wereToDelete && !doDelete ) 
  724.         {
  725.             info->linksToDelete->RemoveAndRelease(link);
  726.             // link->Release(ev);
  727.         }
  728.         else if ( !wereToDelete && doDelete )
  729.         {
  730.             info->linksToDelete->AddLastAndAcquire(link);
  731.             // link->Acquire(ev);
  732.         }
  733.     }
  734.  
  735.     return wereToDelete;
  736.  
  737.     SOM_CATCH_ALL
  738.     SOM_ENDTRY
  739.     return kODFalse;
  740. }
  741.  
  742. //------------------------------------------------------------------------------
  743. // ODLinkManager::CreateLink
  744. //------------------------------------------------------------------------------
  745.  
  746. SOM_Scope ODLinkSource*  SOMLINK ODLinkManagerCreateLink(ODLinkManager *somSelf, Environment *ev,
  747.         ODDraft* draft,
  748.         ODLinkSpec* linkSpec)
  749. {
  750.     ODLinkManagerData *somThis = ODLinkManagerGetData(somSelf);
  751.     ODLinkManagerMethodDebug("ODLinkManager","CreateLink");
  752.  
  753.     ODLinkSource*            linkSource = kODNULL;    ODVolatile(linkSource);
  754.     AppleEvent                theAppleEvent, replyAppleEvent;
  755.     AEAddressDesc            targetAddress;
  756.     OSErr                    error;
  757.     ProcessSerialNumber     psn;
  758.     ProcessSerialNumber     psnLinkSource;
  759.     ODBoolean                isSamePSN;
  760.  
  761.     SOM_TRY
  762.  
  763.         // Create a link source to return
  764.         linkSource = draft->CreateLinkSource(ev, (ODPart*) kODNULL);
  765.  
  766.         // If the draft was created by this process, call the part directly
  767.         GetCurrentProcess(&psn);
  768.         linkSpec->GetOriginatingProcessID(ev, &psnLinkSource);
  769.         SameProcess(&psn, &psnLinkSource, &isSamePSN);
  770.         if ( isSamePSN )
  771.         {
  772.             TempODByteArrayStruct aliasBA;
  773.             somSelf->GetLink(ev, linkSpec, (ODByteArray*) aliasBA);
  774.             somSelf->UseLinkEdition(ev, linkSource, (ODByteArray*) aliasBA);
  775.         }
  776.         else
  777.         {
  778.             // Send an Apple Event to this process specifying a process number
  779.             // address, so the event is delivered as a high-level event
  780.             error = AECreateDesc(typeProcessSerialNumber, &psn,
  781.                                 sizeof(ProcessSerialNumber), &targetAddress);
  782.             THROW_IF_ERROR(error);
  783.             TempAEDesc tmpTargetAddress(&targetAddress);
  784.     
  785.             error = AECreateAppleEvent(kODShellSignature, kODRequestLinkEventID, 
  786.                                 &targetAddress, kAutoGenerateReturnID, 
  787.                                 kAnyTransactionID, &theAppleEvent);
  788.             THROW_IF_ERROR(error);
  789.             TempAEDesc tmpAppleEvent(&theAppleEvent);
  790.         
  791.             // Add the link spec to the Apple event
  792.             linkSpec->WriteToAppleEvent(ev, &theAppleEvent);
  793.             
  794.             // Add the source link to the Apple event
  795.             error = AEPutParamPtr(&theAppleEvent, kODLinkSourceKey, typeLongInteger,
  796.                                 &linkSource, sizeof(linkSource));
  797.             THROW_IF_ERROR(error);
  798.         
  799.             error = AESend(&theAppleEvent, &replyAppleEvent, kAENoReply | kAENeverInteract,
  800.                                 kAENormalPriority, kAEDefaultTimeout, NULL, NULL);
  801.             THROW_IF_ERROR(error);
  802.         }
  803.  
  804.     SOM_CATCH_ALL
  805.     
  806.         ODSafeReleaseObject(linkSource);
  807.         linkSource = kODNULL;
  808.  
  809.     SOM_ENDTRY
  810.  
  811.     return linkSource;
  812. }
  813.  
  814. //------------------------------------------------------------------------------
  815. // GetLinkAEHandler
  816. //------------------------------------------------------------------------------
  817.  
  818. ODStatic OSErr ODPascal GetLinkAEHandler(
  819.         const AppleEvent* theAppleEvent,
  820.         AppleEvent* reply,
  821.         long refCon)
  822. {
  823.     ODLinkManager*        somSelf = (ODLinkManager*)refCon;
  824.     Environment*        ev = somGetGlobalEnvironment ();
  825.     ODLinkSpec*            linkSpec = (ODLinkSpec*) kODNULL; ODVolatile(linkSpec);
  826.     OSErr                error = noErr;
  827.  
  828. #if ODDebug
  829.     somPrintf("ODLinkManager: Get Link event received\n");
  830. #endif
  831.  
  832.     TRY
  833.         linkSpec = new ODLinkSpec;    // Can't use factory method; no draft object!
  834.         THROW_IF_NULL(linkSpec, kODErrOutOfMemory);
  835.         linkSpec->ReadFromAppleEvent(ev, (AppleEvent*) theAppleEvent);
  836.  
  837.         TempODByteArrayStruct aliasBA;
  838.         somSelf->GetLink(ev, linkSpec, (ODByteArray*) aliasBA);
  839.  
  840.         error = AEPutParamPtr(reply, keyEditionAlias, typeAlias,
  841.                             aliasBA->_buffer, aliasBA->_length);
  842.     CATCH_ALL
  843.         // Must catch any exceptions thrown!
  844.         error = ErrorCode();
  845.     ENDTRY
  846.  
  847.     delete linkSpec;
  848.     
  849.     return error;
  850. }
  851.  
  852. //------------------------------------------------------------------------------
  853. // GetLink
  854. //------------------------------------------------------------------------------
  855.  
  856. SOM_Scope void SOMLINK ODLinkManagerGetLink(ODLinkManager *somSelf, Environment *ev,
  857.         ODLinkSpec* linkSpec,
  858.         ODByteArray* aliasData)
  859. {
  860.     ODLinkManagerData *somThis = ODLinkManagerGetData(somSelf);
  861.     ODLinkManagerMethodDebug("ODLinkManager","GetLink");
  862.  
  863.     SOM_TRY
  864.  
  865.         ODPart* part = linkSpec->GetPart(ev);
  866.  
  867.         // If document has never been saved, refuse to create a link
  868.         DraftInfo* info = somSelf->GetDraftInfo(ev, part->GetStorageUnit(ev)->GetDraft(ev));
  869.         THROW_IF_NULL(info, kODErrDocNotSaved);
  870.  
  871.         TempODLink link = kODNULL;
  872.         TempODByteArrayStruct partData = linkSpec->GetPartData(ev);
  873.         ODVolatile(partData);
  874.  
  875.         TempODLinkSource linkSource = kODNULL;
  876.         ODVolatile(linkSource);
  877.  
  878.         linkSource = part->CreateLink(ev, (ODByteArray*) partData);
  879.         THROW_IF_NULL(linkSource, kODErrCannotCreateLink);
  880.         link = linkSource->GetLink(ev);
  881.         THROW_IF_NULL(link, kODErrCannotCreateLink);
  882.         link->Acquire(ev);
  883.     
  884.         ODLinkKey key;    ODVolatile(key);
  885.         if ( link->Lock(ev,0,&key) ) 
  886.         {
  887.             TRY
  888.                 if ( link->GetLinkEdition(ev, key, aliasData) )
  889.                 {
  890.                     // If a new cross-document destination is being created, and the edition
  891.                     // file is waiting for a save to update, force the edition file to update
  892.                     // now so the link content is the same as the content that would be pasted.
  893.                     // [cc; #1190727]
  894.                     DraftInfo* info = somSelf->GetDraftInfo(ev, link->GetStorageUnit(ev)->GetDraft(ev));
  895.                     if ( info && info->linksToExport->Contains(link) ) 
  896.                     {
  897.                         TRY
  898.                             link->UpdateLinkEdition(ev, key);
  899.                             info->linksToExport->RemoveAndRelease(link);
  900.                         CATCH_ALL
  901.                         ENDTRY
  902.                     }
  903.                 }
  904.                 else
  905.                 {
  906.                     ODDraft* draft = part->GetStorageUnit(ev)->GetDraft(ev);
  907.                     ODContainer* container = draft->GetDocument(ev)->GetContainer(ev);;
  908.  
  909.                     TempPlatformFile documentFile = GetPlatformFileFromContainer(ev, container);
  910.                     ODFileSpec documentSpec = documentFile->GetFileSpec();
  911.  
  912.                     EditionContainerSpec editionContainer = NewEditionFile(ev, documentFile, draft);
  913.  
  914.                     link->CreateLinkEdition(ev,
  915.                                             editionContainer,
  916.                                             &documentSpec,
  917.                                             somSelf->NewSectionID(ev, draft),
  918.                                             key,
  919.                                             aliasData);
  920.  
  921.                     info->newExportedLinks->AddLastAndAcquire(link);
  922.                 }
  923.             CATCH_ALL
  924.                 link->Unlock(ev, key);
  925.                 RERAISE;
  926.             ENDTRY
  927.             link->Unlock(ev, key);
  928.         }
  929.             
  930.     SOM_CATCH_ALL
  931.     
  932.     SOM_ENDTRY
  933. }
  934.  
  935. //------------------------------------------------------------------------------
  936. // UseLinkEdition
  937. //------------------------------------------------------------------------------
  938.  
  939. SOM_Scope void SOMLINK ODLinkManagerUseLinkEdition(ODLinkManager *somSelf, Environment *ev,
  940.         ODLinkSource* linkSource,
  941.         ODByteArray* aliasData)
  942. {
  943.     ODLinkManagerData *somThis = ODLinkManagerGetData(somSelf);
  944.     ODLinkManagerMethodDebug("ODLinkManager","UseLinkEdition");
  945.  
  946.     AliasHandle                aliasHandle;
  947.     EditionContainerSpec    editionContainer;
  948.     ODBoolean                wasChanged;
  949.     OSErr                    error;
  950.  
  951.     SOM_TRY
  952.         error = PtrToHand(aliasData->_buffer, (Handle*) &aliasHandle, aliasData->_length);
  953.         THROW_IF_ERROR(error);
  954.         TempODHandle editionAlias((ODHandle) aliasHandle);
  955.  
  956.         error = ResolveAlias(nil, aliasHandle, &editionContainer.theFile, &wasChanged);
  957.         THROW_IF_ERROR(error);
  958.     
  959.         editionContainer.theFileScript = smSystemScript;
  960.         editionContainer.thePart = kPartsNotUsed;
  961.     
  962.         ODDraft* draft = linkSource->GetStorageUnit(ev)->GetDraft(ev);
  963.     
  964.         ODContainer* container = draft->GetDocument(ev)->GetContainer(ev);;
  965.         ODFileSpec documentSpec = GetODFileSpecFromContainer(ev, container);
  966.     
  967.         ODLinkKey key;    ODVolatile(key);
  968.         if ( linkSource->Lock(ev,0,&key) ) 
  969.         {
  970.             TRY
  971.                 linkSource->UseLinkEdition(ev,
  972.                                     editionContainer, 
  973.                                     &documentSpec,
  974.                                     somSelf->NewSectionID(ev, draft),
  975.                                     key);
  976.             CATCH_ALL
  977.                 linkSource->Unlock(ev, key);
  978.                 RERAISE;
  979.             ENDTRY
  980.             linkSource->Unlock(ev, key);
  981.         }
  982.  
  983.     SOM_CATCH_ALL
  984.     
  985.     SOM_ENDTRY
  986. }
  987.  
  988. //------------------------------------------------------------------------------
  989. // RequestLinkAEHandler
  990. //------------------------------------------------------------------------------
  991.  
  992. ODStatic OSErr ODPascal RequestLinkAEHandler(
  993.         const AppleEvent* requestLinkAppleEvent,
  994.         AppleEvent* reply,
  995.         long refCon)
  996. {
  997.     ODLinkManager*            somSelf = (ODLinkManager*) refCon;
  998.     Environment*            ev = somGetGlobalEnvironment();
  999.     AppleEvent                getLinkAppleEvent;
  1000.     AppleEvent                replyAppleEvent;
  1001.     AEAddressDesc            targetAddress;
  1002.     ProcessSerialNumber     psn;
  1003.     DescType                returnedType;
  1004.     Size                    actualSize;
  1005.     OSErr                    error;
  1006.     const long                kGetLinkReplyTimeout = 600;    // Ten seconds
  1007.     
  1008.     ODLinkSource*    linkSource = kODNULL;    ODVolatile(linkSource);
  1009.     ODLinkSpec*        linkSpec = kODNULL;        ODVolatile(linkSpec);
  1010.  
  1011.     TRY
  1012.     
  1013.         linkSpec = new ODLinkSpec;    // Can't use factory method; no draft object!
  1014.         THROW_IF_NULL(linkSpec, kODErrOutOfMemory);
  1015.  
  1016.         linkSpec->ReadFromAppleEvent(ev, (AppleEvent*) requestLinkAppleEvent);
  1017.  
  1018.         error = AEGetParamPtr(requestLinkAppleEvent, kODLinkSourceKey,
  1019.                                 typeLongInteger, &returnedType,
  1020.                                 &linkSource, sizeof(linkSource), &actualSize);
  1021.         THROW_IF_ERROR(error);
  1022.  
  1023.         // Create the GetLink event
  1024.         
  1025.         linkSpec->GetOriginatingProcessID(ev, &psn);
  1026.     
  1027.         error = AECreateDesc(typeProcessSerialNumber, &psn,
  1028.                             sizeof(ProcessSerialNumber), &targetAddress);
  1029.         THROW_IF_ERROR(error);
  1030.         TempAEDesc tmpTargetAddress(&targetAddress);
  1031.  
  1032.         error = AECreateAppleEvent(kODShellSignature, kODGetLinkEventID, 
  1033.                             &targetAddress, kAutoGenerateReturnID, 
  1034.                             kAnyTransactionID, &getLinkAppleEvent);
  1035.         THROW_IF_ERROR(error);
  1036.         TempAEDesc tmpGetLinkAppleEvent(&getLinkAppleEvent);
  1037.     
  1038.         linkSpec->WriteToAppleEvent(ev, &getLinkAppleEvent);
  1039.         
  1040.         error = AESend(&getLinkAppleEvent, &replyAppleEvent, 
  1041.                             kAEWaitReply | kAENeverInteract, kAENormalPriority,
  1042.                             kGetLinkReplyTimeout, NULL, NULL);
  1043.         TempAEDesc tmpReplyAppleEvent(&replyAppleEvent);
  1044.         THROW_IF_ERROR(error);
  1045.  
  1046.         // Process the reply
  1047.  
  1048.         TempODByteArray aliasData = ODAEGetByteArray(&replyAppleEvent, keyEditionAlias, typeAlias);
  1049.         somSelf->UseLinkEdition(ev, linkSource, aliasData);
  1050.         
  1051.     CATCH_ALL
  1052.     
  1053.         if ( linkSource )
  1054.         {
  1055.             linkSource->SetStatus(ev, kODErrCannotEstablishLink);
  1056.  
  1057.             // Ignore errors returned by UpdateDependents
  1058.             TRY
  1059.                 linkSource->GetLink(ev)->UpdateDependents(ev);
  1060.             CATCH_ALL
  1061.             ENDTRY
  1062.         }
  1063.  
  1064.     ENDTRY
  1065.  
  1066.     ODDeleteObject(linkSpec);
  1067.  
  1068.     return noErr;
  1069. }
  1070.  
  1071. //------------------------------------------------------------------------------
  1072. // SectionReadAEHandler
  1073. //------------------------------------------------------------------------------
  1074.  
  1075. ODStatic OSErr ODPascal SectionReadAEHandler(
  1076.         const AppleEvent* theAppleEvent,
  1077.         const AppleEvent* reply,
  1078.         long refCon)
  1079. {
  1080.     ODUnused(reply);
  1081.  
  1082.     ODLinkManager*        somSelf = (ODLinkManager*)refCon;
  1083.     Environment*        ev = somGetGlobalEnvironment ();
  1084.     SectionHandle        section = kODNULL;
  1085.     OSErr                error;
  1086.  
  1087.     error = GetSectionFromEvent(theAppleEvent, §ion);
  1088.  
  1089. #if ODDebug
  1090.         somPrintf("ODLinkManager: Section Read event received; section = %x, linkSource = %x\n",
  1091.                     section, (**section).refCon);
  1092. #endif
  1093.  
  1094.     if ( error == noErr )
  1095.     {
  1096.         if ( IsRegisteredSection(section) == noErr ) 
  1097.         {
  1098.             ODLinkSource* linkSource = (ODLinkSource*) (*section)->refCon;
  1099.             ODLinkKey key;
  1100.  
  1101.             if ( linkSource->Lock(ev,0,&key) ) 
  1102.             {
  1103.                 TRY
  1104.                     linkSource->ReadLinkEdition(ev,key);
  1105.                     DraftInfo* info = somSelf->GetDraftInfo(ev, linkSource->GetStorageUnit(ev)->GetDraft(ev));
  1106.                     if ( info != (DraftInfo*) kODNULL ) 
  1107.                     {
  1108.                         info->linksImported = kODTrue;
  1109.                     }
  1110.                 CATCH_ALL
  1111.                     error = ErrorCode();
  1112.                 ENDTRY
  1113.                 linkSource->Unlock(ev, key);
  1114.             }
  1115.         }
  1116.     }
  1117.  
  1118.     return error;
  1119. }
  1120.  
  1121. //------------------------------------------------------------------------------
  1122. // SectionWriteAEHandler
  1123. //------------------------------------------------------------------------------
  1124.  
  1125. ODStatic OSErr ODPascal SectionWriteAEHandler(
  1126.         const AppleEvent* theAppleEvent,
  1127.         const AppleEvent* reply,
  1128.         long refCon)
  1129. {
  1130.     ODUnused(reply);
  1131.  
  1132.     ODLinkManager*        somSelf = (ODLinkManager*)refCon;
  1133.     Environment*        ev = somGetGlobalEnvironment ();
  1134.     ODLinkKey            key;
  1135.     SectionHandle        section = kODNULL;
  1136.     OSErr                error;
  1137.  
  1138.     error = GetSectionFromEvent(theAppleEvent, §ion);
  1139.  
  1140. #if ODDebug
  1141.         somPrintf("ODLinkManager: Section Write event received; section = %x, link = %x\n",
  1142.                     section, (**section).refCon);
  1143. #endif
  1144.  
  1145.     if ( error == noErr )
  1146.     {
  1147.         if ( IsRegisteredSection(section) == noErr ) 
  1148.         {
  1149.             ODLink* link = (ODLink*) (**section).refCon;
  1150.  
  1151.             // Force ExportLinkEdition to write the edition file
  1152.             (**section).mdDate = (TimeStamp) 0;
  1153.  
  1154.             if ( link->Lock(ev,0,&key) ) 
  1155.             {
  1156.                 TRY
  1157.                     link->UpdateLinkEdition(ev, key);
  1158.                 CATCH_ALL
  1159.                     error = ErrorCode();
  1160.                 ENDTRY
  1161.                 link->Unlock(ev, key);
  1162.             }
  1163.         }
  1164.     }
  1165.  
  1166.     return error;
  1167. }
  1168.  
  1169. //------------------------------------------------------------------------------
  1170. // BuildErrorString
  1171. //------------------------------------------------------------------------------
  1172.  
  1173. ODStatic StringPtr BuildErrorString(ODSShort strResourceID, ODError error)
  1174. {
  1175.     Str63 numberString;
  1176.     Str255 msgStr;
  1177.  
  1178.     StringPtr result = kODNULL;
  1179.     
  1180.     ODSLong savedRefNum;
  1181.     BeginUsingLibraryResources(savedRefNum);
  1182.  
  1183.     NumToString(error, numberString);
  1184.     ReplaceIntoString(strResourceID, numberString, kODNULL, msgStr);
  1185.  
  1186.     if ( msgStr[0] > 0 )
  1187.     {
  1188.         ODULong ptrSize = msgStr[0]+1;
  1189.         result = (StringPtr) ODNewPtr(ptrSize);
  1190.         if ( result )
  1191.             ODBlockMove((ODPtr) &msgStr, (ODPtr) result, ptrSize);
  1192.     }
  1193.     
  1194.     EndUsingLibraryResources(savedRefNum);
  1195.     
  1196.     return result;
  1197. }
  1198.  
  1199. //------------------------------------------------------------------------------
  1200. // SectionScrollAEHandler
  1201. //------------------------------------------------------------------------------
  1202.  
  1203. ODStatic OSErr ODPascal SectionScrollAEHandler(
  1204.         const AppleEvent* theAppleEvent,
  1205.         const AppleEvent* reply,
  1206.         long refCon)
  1207. {
  1208.     ODUnused(reply);
  1209.  
  1210.     ODLinkManager*        somSelf = (ODLinkManager*)refCon;
  1211.     ODLinkManagerData*    somThis = ODLinkManagerGetData(somSelf);
  1212.     Environment*        ev = somGetGlobalEnvironment ();
  1213.     SectionHandle        section = kODNULL;
  1214.     OSErr                error;
  1215.  
  1216.     error = GetSectionFromEvent(theAppleEvent, §ion);
  1217.  
  1218. #if ODDebug
  1219.     somPrintf("ODLinkManager: Section Scroll event received; section = %x, link = %x\n",
  1220.                     section, (section ? (**section).refCon : 0));
  1221. #endif
  1222.  
  1223.     if ( error == noErr )
  1224.     {
  1225.         if ( IsRegisteredSection(section) == noErr ) 
  1226.         {
  1227.             TRY
  1228.             ODLink* link = (ODLink*) (**section).refCon;
  1229.  
  1230.             if ( link != kODNULL )
  1231.             {
  1232.                 DraftInfo* info = somSelf->GetDraftInfo(ev, link->GetStorageUnit(ev)->GetDraft(ev));
  1233.                 if ( info && info->linksToDelete && info->linksToDelete->Contains(link) ) 
  1234.                     THROW(kODErrCannotRevealLink);
  1235.                 else
  1236.                     link->ShowSourceContent(ev);
  1237.             }
  1238.             CATCH_ALL
  1239.                 error = ErrorCode();
  1240.                                 
  1241.                 NMRemove(_fNMRecPtr);    // ensure not already queued
  1242.                 _fNMRecPtr->qType = nmType;
  1243.                 _fNMRecPtr->nmMark = 0;
  1244.                 _fNMRecPtr->nmIcon = nil;
  1245.                 _fNMRecPtr->nmSound = nil;
  1246.                 ODDisposePtr((ODPtr) _fNMRecPtr->nmStr);
  1247.                 _fNMRecPtr->nmStr = BuildErrorString(kODLinkMgrCannotShowSourceID, error);
  1248.                 _fNMRecPtr->nmResp = _fNMResponseUPP;
  1249.                 error = NMInstall(_fNMRecPtr);
  1250.             ENDTRY
  1251.         }
  1252.     }
  1253.  
  1254.     return error;
  1255. }
  1256.  
  1257. //------------------------------------------------------------------------------
  1258. // NewEditionFile
  1259. //------------------------------------------------------------------------------
  1260.  
  1261. ODStatic EditionContainerSpec NewEditionFile(Environment* ev,
  1262.             PlatformFile* documentFile,
  1263.             ODDraft* draft)
  1264. {
  1265.     EditionContainerSpec    editionContainer;
  1266.     OSErr                    error;
  1267.     Str255                    documentName;
  1268.     ODFileSpec                documentSpec = documentFile->GetFileSpec();
  1269.  
  1270.     do {
  1271.         documentFile->GetAsciiName((char *) documentName, 254);
  1272.         CToPascalString((char *) documentName);
  1273.         EditionFileName(documentName, (ODUShort) NewEditionID(ev, draft));
  1274.         error = FSMakeFSSpec(documentSpec.vRefNum,
  1275.                              documentSpec.parID,
  1276.                              documentName,
  1277.                              &(editionContainer.theFile));
  1278.         }
  1279.     while (error == noErr);
  1280.  
  1281.     // Expect a file not found error
  1282.     if ( error != fnfErr )
  1283.         THROW_IF_ERROR(error);
  1284.  
  1285.     editionContainer.theFileScript = smSystemScript;
  1286.     editionContainer.thePart = kPartsNotUsed;
  1287.     
  1288.     return editionContainer;
  1289. }
  1290.  
  1291. //------------------------------------------------------------------------------
  1292. // GetSectionFromEvent
  1293. //------------------------------------------------------------------------------
  1294.  
  1295. ODStatic OSErr GetSectionFromEvent(const AppleEvent* theAppleEvent,
  1296.                 SectionHandle* section)
  1297. {
  1298.     DescType        returnedType;
  1299.     Size            actualSize;
  1300.     OSErr            error;
  1301.  
  1302.     error = AEGetParamPtr(theAppleEvent, keyDirectObject, typeSectionH, &returnedType,
  1303.                             section, sizeof(*section), &actualSize);
  1304. #if ODDebug
  1305.     if ( error != noErr )
  1306.         somPrintf("ODLinkManager: Error %d getting section from event\n", error);
  1307. #endif
  1308.  
  1309.     return error;
  1310. }
  1311.  
  1312. //------------------------------------------------------------------------------
  1313. // EditionFileName
  1314. //------------------------------------------------------------------------------
  1315.  
  1316. ODStatic void EditionFileName(Str255 fileName, ODUShort numb)
  1317. {
  1318.     Str63 numberString;
  1319.  
  1320.     NumToString(numb, numberString);
  1321.  
  1322.     TruncateFileName(fileName, numberString);
  1323.  
  1324.     ODSLong savedRefNum;
  1325.     BeginUsingLibraryResources(savedRefNum);
  1326.  
  1327.     ReplaceIntoString(kODLinkMgrEditionTemplateID, fileName, numberString, fileName);
  1328.  
  1329.     EndUsingLibraryResources(savedRefNum);
  1330. }
  1331.  
  1332. //------------------------------------------------------------------------------
  1333. // TruncateFileName
  1334. //------------------------------------------------------------------------------
  1335.  
  1336. ODStatic void TruncateFileName(Str255 fileName, Str63 numberString)
  1337. {
  1338.     const maxFileNameLength = 31;
  1339.  
  1340.     Str255 emptyString;
  1341.     emptyString[0] = (unsigned char) 0;
  1342.  
  1343.     ODSLong savedRefNum;
  1344.     BeginUsingLibraryResources(savedRefNum);
  1345.  
  1346.     ReplaceIntoString(kODLinkMgrEditionTemplateID, emptyString, numberString, emptyString);
  1347.     
  1348.     EndUsingLibraryResources(savedRefNum);
  1349.  
  1350.     if ( (StrLength(fileName)+StrLength(emptyString)) > maxFileNameLength )
  1351.         ClipStringToBytes( fileName,
  1352.                 maxFileNameLength-StrLength(emptyString), smCurrentScript );
  1353. }
  1354.  
  1355. //------------------------------------------------------------------------------
  1356. // NewEditionID
  1357. //------------------------------------------------------------------------------
  1358.  
  1359. ODStatic ODULong NewEditionID(Environment *ev, ODDraft* draft)
  1360. {
  1361.     return ReserveGlobalID(ev, draft, kODPropEditionID);
  1362. }
  1363.  
  1364. //------------------------------------------------------------------------------
  1365. // PeekNextGlobalID
  1366. //------------------------------------------------------------------------------
  1367.  
  1368. ODStatic ODULong PeekNextGlobalID(Environment *ev,
  1369.         ODDraft* draft,
  1370.         ODPropertyName globalProp)
  1371. {
  1372.     TempODStorageUnit    draftPropertiesSU = draft->AcquireDraftProperties(ev);
  1373.     ODULong            id = 0;
  1374.     
  1375.     if ( ODSUExistsThenFocus(ev, draftPropertiesSU, globalProp, kODULong) )
  1376.         StorageUnitGetValue(draftPropertiesSU, ev, sizeof(ODULong), (ODValue) &id);
  1377.  
  1378.     return ++id;
  1379. }
  1380.  
  1381. //------------------------------------------------------------------------------
  1382. // ReserveGlobalID
  1383. //------------------------------------------------------------------------------
  1384.  
  1385. ODStatic ODULong ReserveGlobalID(Environment *ev,
  1386.         ODDraft* draft,
  1387.         ODPropertyName globalProp)
  1388. {
  1389.     TempODStorageUnit    draftPropertiesSU = draft->AcquireDraftProperties(ev);
  1390.     ODULong            id = 0;
  1391.     
  1392.     ODSUForceFocus(ev, draftPropertiesSU, globalProp, kODULong);
  1393.     if ( draftPropertiesSU->GetSize(ev) > 0 )
  1394.         id = ODGetULongProp(ev, draftPropertiesSU, globalProp, kODULong);
  1395.     ++id;
  1396.     ODSetULongProp(ev, draftPropertiesSU, globalProp, kODULong, id);
  1397.     
  1398.     return id;
  1399. }
  1400.  
  1401. //------------------------------------------------------------------------------
  1402. // ODLinkManager::NewDraftInfo
  1403. //------------------------------------------------------------------------------
  1404.  
  1405. SOM_Scope void  SOMLINK ODLinkManagerNewDraftInfo(ODLinkManager *somSelf, Environment *ev,
  1406.         ODDraft* draft)
  1407. {
  1408.     ODLinkManagerData *somThis = ODLinkManagerGetData(somSelf);
  1409.     ODLinkManagerMethodDebug("ODLinkManager","NewDraftInfo");
  1410.  
  1411.     SOM_TRY
  1412.  
  1413.     // Create a new info structure for this draft
  1414.     DraftInfo* info = new DraftInfo;
  1415.  
  1416.     info->draft = draft;
  1417.     info->linksToExport = new ODRefCntCollection(ev);
  1418.     info->linksToDelete = new ODRefCntCollection(ev);
  1419.     info->newExportedLinks = new ODRefCntCollection(ev);
  1420.     info->linksImported = kODFalse;
  1421.     _fDraftInfos->AddLast(info);
  1422.  
  1423.     SOM_CATCH_ALL
  1424.     SOM_ENDTRY
  1425. }
  1426.  
  1427. //------------------------------------------------------------------------------
  1428. // ODLinkManager::GetDraftInfo
  1429. //------------------------------------------------------------------------------
  1430.  
  1431. SOM_Scope DraftInfo*  SOMLINK ODLinkManagerGetDraftInfo(ODLinkManager *somSelf, Environment *ev,
  1432.         ODDraft* draft)
  1433. {
  1434.     ODLinkManagerData *somThis = ODLinkManagerGetData(somSelf);
  1435.     ODLinkManagerMethodDebug("ODLinkManager","GetDraftInfo");
  1436.  
  1437.     OrderedCollectionIterator* iter = kODNULL; ODVolatile(iter);
  1438.     
  1439.     DraftInfo* result = (DraftInfo*) kODNULL;
  1440.     
  1441.     if ( draft && _fDraftInfos )
  1442.     {
  1443.         TRY
  1444.             iter = _fDraftInfos->CreateIterator();
  1445.  
  1446.             for (DraftInfo* info = (DraftInfo*) iter->First();
  1447.                     iter->IsNotComplete();
  1448.                     info = (DraftInfo*) iter->Next() )
  1449.             {
  1450.                 if ( info && draft->IsEqualTo(ev, info->draft) ) 
  1451.                 {
  1452.                     result = info;
  1453.                     break;
  1454.                 }
  1455.             }
  1456.         CATCH_ALL
  1457.         ENDTRY
  1458.  
  1459.         ODDeleteObject(iter);
  1460.     }
  1461.  
  1462.     return result;
  1463. }
  1464.  
  1465. //------------------------------------------------------------------------------
  1466. // ODLinkManager::DeleteDraftInfos
  1467. //------------------------------------------------------------------------------
  1468.  
  1469. // SOM_Scope void  SOMLINK ODLinkManagerDeleteDraftInfos(ODLinkManager *somSelf, Environment *ev)
  1470. // {
  1471. //     ODLinkManagerData *somThis = ODLinkManagerGetData(somSelf);
  1472. //     ODLinkManagerMethodDebug("ODLinkManager","DeleteDraftInfos");
  1473. // 
  1474. //     SOM_CATCH return;
  1475. //     
  1476. //     if (_fDraftInfos != (OrderedCollection*) kODNULL)
  1477. //     {
  1478. //         DraftInfo* info;
  1479. //         while ((info = (DraftInfo*) _fDraftInfos->First()) != (DraftInfo*) kODNULL)
  1480. //         {
  1481. //             ODDeleteObject(info->linksToExport);
  1482. //             ODDeleteObject(info->linksToDelete);
  1483. //             ODDeleteObject(info->newExportedLinks);
  1484. //             _fDraftInfos->RemoveFirst();
  1485. //             delete info;
  1486. //         }
  1487. //         ODDeleteObject(_fDraftInfos);
  1488. //     }
  1489. // }
  1490.  
  1491. //------------------------------------------------------------------------------
  1492. // ODLinkManager::somUninit
  1493. //------------------------------------------------------------------------------
  1494.  
  1495. SOM_Scope void  SOMLINK ODLinkManagersomUninit(ODLinkManager *somSelf)
  1496. {
  1497.     ODLinkManagerData *somThis = ODLinkManagerGetData(somSelf);
  1498.     ODLinkManagerMethodDebug("ODLinkManager","somUninit");
  1499.  
  1500.     AEEventHandlerUPP    toBeDisposedUPP;
  1501.     long                toBeIgnoredRefCon;
  1502.     OSErr                error;
  1503.  
  1504.     // somSelf->DeleteDraftInfos(ev);
  1505.     // It is incorrect to call methods on somSelf inside somUninit, 
  1506.     // a subclass may have already been somUninited.  See OpenDoc Building Code for details.
  1507.     // Instead the implementation of DeleteDraftInfos has been copied here.
  1508.     
  1509.     // BEGIN copy of DeleteDraftInfos implementation
  1510.     if (_fDraftInfos != (OrderedCollection*) kODNULL )
  1511.     {
  1512.         Environment* ev = somGetGlobalEnvironment();
  1513.         DraftInfo* info;
  1514.         while ((info = (DraftInfo*) _fDraftInfos->First()) != (DraftInfo*) kODNULL)
  1515.         {
  1516.             ODDeleteObject(info->linksToExport);
  1517.             ODDeleteObject(info->linksToDelete);
  1518.             ODDeleteObject(info->newExportedLinks);
  1519.             _fDraftInfos->RemoveFirst();
  1520.             delete info;
  1521.         }
  1522.         ODDeleteObject(_fDraftInfos);
  1523.     }
  1524.     // END copy of DeleteDraftInfos implementation
  1525.  
  1526.     if ( _fSuspendedUpdateLinks != (ODRefCntCollection*) kODNULL ) 
  1527.     {
  1528.         // _fSuspendedUpdateLinks->RemoveAndReleaseAll();
  1529.         ODDeleteObject(_fSuspendedUpdateLinks);
  1530.     }
  1531.  
  1532.     error = AEGetEventHandler(kODShellSignature, kODGetLinkEventID,
  1533.             &toBeDisposedUPP, &toBeIgnoredRefCon, kNotSysHandler);
  1534.     if ( error == noErr )
  1535.     {
  1536.         DisposeRoutineDescriptor(toBeDisposedUPP);
  1537.         error = AERemoveEventHandler(kODShellSignature, kODGetLinkEventID,
  1538.                     kODNULL,        // a UPP wouldn't work: it might not be ==
  1539.                     kNotSysHandler);
  1540.     }
  1541.  
  1542.     error = AEGetEventHandler(kODShellSignature, kODRequestLinkEventID,
  1543.             &toBeDisposedUPP, &toBeIgnoredRefCon, kNotSysHandler);
  1544.     if ( error == noErr )
  1545.     {
  1546.         DisposeRoutineDescriptor(toBeDisposedUPP);
  1547.         error = AERemoveEventHandler(kODShellSignature, kODRequestLinkEventID,
  1548.                     kODNULL,        // a UPP wouldn't work: it might not be ==
  1549.                     kNotSysHandler);
  1550.     }
  1551.  
  1552.     error = AEGetEventHandler(sectionEventMsgClass, sectionReadMsgID,
  1553.             &toBeDisposedUPP, &toBeIgnoredRefCon, kNotSysHandler);
  1554.     if ( error == noErr )
  1555.     {
  1556.         DisposeRoutineDescriptor(toBeDisposedUPP);
  1557.         error = AERemoveEventHandler(sectionEventMsgClass, sectionReadMsgID,
  1558.                     kODNULL,
  1559.                     kNotSysHandler);
  1560.     }
  1561.  
  1562.     error = AEGetEventHandler(sectionEventMsgClass, sectionWriteMsgID,
  1563.             &toBeDisposedUPP, &toBeIgnoredRefCon, kNotSysHandler);
  1564.     if ( error == noErr )
  1565.     {
  1566.         DisposeRoutineDescriptor(toBeDisposedUPP) ;
  1567.         error = AERemoveEventHandler(sectionEventMsgClass, sectionWriteMsgID,
  1568.                     kODNULL,
  1569.                     kNotSysHandler);
  1570.     }
  1571.  
  1572.     error = AEGetEventHandler(sectionEventMsgClass, sectionScrollMsgID,
  1573.             &toBeDisposedUPP, &toBeIgnoredRefCon, kNotSysHandler);
  1574.     if ( error == noErr )
  1575.     {
  1576.         DisposeRoutineDescriptor(toBeDisposedUPP) ;
  1577.         error = AERemoveEventHandler(sectionEventMsgClass, sectionScrollMsgID,
  1578.                     kODNULL,
  1579.                     kNotSysHandler);
  1580.     }
  1581.  
  1582.     if ( _fNMResponseUPP != kODNULL )
  1583.         DisposeRoutineDescriptor(_fNMResponseUPP);
  1584.  
  1585.     if ( _fNMRecPtr )
  1586.         ODDisposePtr((ODPtr) _fNMRecPtr->nmStr);
  1587.     ODDisposePtr(_fNMRecPtr);
  1588.  
  1589.     parent_somUninit(somSelf);
  1590. }
  1591.  
  1592. //------------------------------------------------------------------------------
  1593. // RegisterSubscribingLinks
  1594. //------------------------------------------------------------------------------
  1595.  
  1596. ODStatic void RegisterSubscribingLinks(Environment *ev, ODDraft* draft)
  1597. {
  1598.     // Internalize all link source objects; each link subscribing to an edition
  1599.     // file will register with the edition manager.
  1600.  
  1601.     ODLinkSourceIterator* iter;
  1602.  
  1603.     iter = draft->CreateLinkSourceIterator(ev);
  1604.  
  1605.     TRY{
  1606.         for (ODLinkSource* linkSource = iter->First(ev);
  1607.                 iter->IsNotComplete(ev);
  1608.                 linkSource = iter->Next(ev) )
  1609.         {
  1610.             linkSource->Release(ev);
  1611.         }
  1612.     }CATCH_ALL{
  1613.     }ENDTRY
  1614.  
  1615.     delete iter;
  1616. }
  1617.  
  1618. //------------------------------------------------------------------------------
  1619. // RegisterPublishingLinks
  1620. //------------------------------------------------------------------------------
  1621. ODStatic void RegisterPublishingLinks(Environment *ev, ODDraft* draft)
  1622. {
  1623.     // Internalize all link objects; each link publishing an edition file will 
  1624.     // register with the edition manager.
  1625.  
  1626.     ODLinkIterator* iter;
  1627.     
  1628.     iter = draft->CreateLinkIterator(ev);
  1629.  
  1630.     TRY{
  1631.         for (ODLink* link = iter->First(ev);
  1632.                 iter->IsNotComplete(ev);
  1633.                 link = iter->Next(ev) )
  1634.         {
  1635.             link->Release(ev);
  1636.         }
  1637.     }CATCH_ALL{
  1638.     }ENDTRY
  1639.  
  1640.     delete iter;
  1641. }
  1642.  
  1643. //------------------------------------------------------------------------------
  1644. // UpdateEditionFiles
  1645. //------------------------------------------------------------------------------
  1646.  
  1647. ODStatic void UpdateEditionFiles(Environment *ev, ODRefCntCollection* collection)
  1648. {
  1649.     if ( collection != kODNULL )
  1650.     {
  1651.         ODRefCntCollectionIterator iter(collection);
  1652.         ODLinkKey key;
  1653.     
  1654.         for (ODLink* link = (ODLink*) iter.First();
  1655.                 iter.IsNotComplete();
  1656.                 link = (ODLink*) iter.Next() )
  1657.         {
  1658.             if ( link->Lock(ev,0,&key) ) 
  1659.             {
  1660.                 TRY
  1661.                     link->UpdateLinkEdition(ev, key);
  1662.                 CATCH_ALL
  1663.                 ENDTRY
  1664.                 link->Unlock(ev, key);
  1665.             }
  1666.         }
  1667.     }
  1668. }
  1669.  
  1670. //------------------------------------------------------------------------------
  1671. // DeleteEditionFiles
  1672. //------------------------------------------------------------------------------
  1673.  
  1674. ODStatic void DeleteEditionFiles(Environment *ev, ODRefCntCollection* collection)
  1675. {
  1676.     if ( collection != kODNULL )
  1677.     {
  1678.         ODRefCntCollectionIterator iter(collection);
  1679.         ODLinkKey key;
  1680.     
  1681.         for (ODLink* link = (ODLink*) iter.First();
  1682.                 iter.IsNotComplete();
  1683.                 link = (ODLink*) iter.Next() )
  1684.         {
  1685.             if ( link->Lock(ev,0,&key) ) 
  1686.             {
  1687.                 TRY
  1688.                     link->DeleteLinkEdition(ev, key);
  1689.                 CATCH_ALL
  1690.                 ENDTRY
  1691.                 link->Unlock(ev, key);
  1692.             }
  1693.         }
  1694.     }
  1695. }
  1696.  
  1697. //------------------------------------------------------------------------------
  1698. // RemoveAllLinksInCollection
  1699. //------------------------------------------------------------------------------
  1700.  
  1701. // ODStatic void RemoveAllLinksInCollection(Environment *ev, ODRefCntCollection* collection)
  1702. //     // collection must contain only ODLink subclass instances
  1703. // {
  1704. //     if ( collection != kODNULL )
  1705. //     {
  1706. //         ODRefCntCollectionIterator iter(collection);
  1707. //         
  1708. //         TRY
  1709. //             for (ODLink* link = (ODLink*) iter->First();
  1710. //                     iter->IsNotComplete();
  1711. //                     link = (ODLink*) iter->Next() )
  1712. //             {
  1713. //                 ODReleaseObject(ev, link);
  1714. //             }
  1715. //         CATCH_ALL
  1716. //         ENDTRY
  1717. //     
  1718. //         collection->RemoveAll();
  1719. //     }
  1720. // }
  1721.  
  1722. //------------------------------------------------------------------------------
  1723. // AppendULongToDraftProperty
  1724. //------------------------------------------------------------------------------
  1725.  
  1726. ODStatic void AppendULongToDraftProperty(Environment *ev,
  1727.     ODDraft* draft, ODPropertyName prop, ODULong value)
  1728. {
  1729.     TempODStorageUnit draftProperties = draft->AcquireDraftProperties(ev);
  1730.     ODSUForceFocus(ev, draftProperties, prop, kODULongSequence);
  1731.     draftProperties->SetOffset(ev, draftProperties->GetSize(ev));
  1732.     ODSetULongProp(ev, draftProperties, kODNULL, kODNULL, value);
  1733.     
  1734.     draft->SetChangedFromPrev(ev);
  1735. }
  1736.  
  1737. //------------------------------------------------------------------------------
  1738. // SectionIDReserved
  1739. //------------------------------------------------------------------------------
  1740.  
  1741. ODStatic ODBoolean SectionIDReserved(Environment *ev,
  1742.     ODDraft* draft, ODULong requestedID)
  1743. {
  1744.     ODBoolean result = kODFalse;
  1745.  
  1746.     TempODStorageUnit draftProperties = draft->AcquireDraftProperties(ev);
  1747.  
  1748.     if ( ODSUExistsThenFocus(ev, draftProperties, kODPropReservedSectionIDs, kODULongSequence) )
  1749.     {
  1750.         ODULong size = draftProperties->GetSize(ev);
  1751.         while ( draftProperties->GetOffset(ev) < size )
  1752.         {
  1753.             if ( ODGetULongProp(ev, draftProperties, kODNULL, kODNULL) == requestedID )
  1754.             {
  1755.                 result = kODTrue;
  1756.                 break;
  1757.             }
  1758.         }
  1759.     }
  1760.  
  1761.     return result;
  1762. }
  1763.